//
// @project：Pods
// @file：JWGuideMarkerManager.swift
// @author：linjw(10126121@qq.com)
// @time: 2023/5/1
//

import UIKit

public typealias JWGuideMarkerManagerHandleFinishAction = ((Bool) -> ())

/// 新手引导管理器
public class JWGuideMarkerManager: NSObject {
    
    /// 数据源
    public weak var dataSource: JWGuideMarkerManagerDataSource?
    
    /// 父类
    private weak var parentView: UIView!
    
    /// 当前引导标识
    public var currentGuideIndex: Int { currentIndex }
    private var currentIndex: Int = 0
    
    /// 当前引导视图
    private var currentMarkerView: UIView? = nil
    
    /// 动画变化量
    private var animationEffectOffsetValue: CGFloat = 10
    
    /// 完成引导
    public var handleFinishAction: JWGuideMarkerManagerHandleFinishAction? = nil
    
    public init(parentView: UIView) {
        self.parentView = parentView
    }
    
    /// 显示引导标识(注意：要先设置dataSource和parentView)
    public func showGuideMarker() {
        
        guard let ds = dataSource else {
            assert(false, "JWGuideMarkerManager.Error.请先配置数据源")
            return
        }
        
        let totalCount = ds.guideMarkerNumbers(self)
        if totalCount > 0 {
            if currentIndex < totalCount {
                let datas = ds.guideMarker(self, markerForItemAtIndex: currentIndex)
                changeGuideMarker(data: datas)
            } else {
                removeMarker(isAnimation: true) { [weak self] in
                    self?.guideMarkerFinish(isSkip: false)
                }
            }
        } else {
            debugPrint("JWGuideMarkerManager.Error.数据源为0")
        }
        
    }
    
    /// 下一个
    public func nextCoachMarker() {
        showGuideMarker()
    }
    
    /// 跳过
    public func skipGuideMarker() {
        removeMarker(isAnimation: true) { [weak self] in
            self?.guideMarkerFinish(isSkip: true)
        }
    }
    
    /// 重置
    public func reset() {
        currentIndex = 0
        removeMarker(isAnimation: false)
    }
    
    /// 引导完成
    private func guideMarkerFinish(isSkip: Bool) {
        self.handleFinishAction?(isSkip)
    }
    
    /// 移除引导
    private func removeMarker(isAnimation: Bool = true, completion: (() -> Void)? = nil) {
        
        if isAnimation {
            UIView.animate(withDuration: 0.25, animations: { [weak self] in
                self?.currentMarkerView?.alpha = 0.3
            }) { [weak self] _ in
                guard let self = self else { return }
                self.currentMarkerView?.removeFromSuperview()
                self.currentMarkerView = nil
                completion?()
            }
        } else {
            currentMarkerView?.removeFromSuperview()
            currentMarkerView = nil
            completion?()
        }
    }
    
    
    /// 切换引导
    private func changeGuideMarker(data: JWGuideMarkerData) {
        removeMarker(isAnimation: true) { [weak self] in
            guard let self = self else { return }
            switch data.animationStyle {
            case .none:
                self.currentMarkerView = self.createOverlay(frame: CGRect(origin: data.point, size: data.size),
                                                            radius: data.radius,
                                                            animationStyle: .none)
                break
            case .scale:
                let centerPoint = CGPoint(x: data.frame.midX, y: data.frame.midY)
                self.currentMarkerView = self.createOverlayCircle(offset: centerPoint,
                                                                  radius: data.radius,
                                                                  animationStyle: .scale)
                //                self.currentMarkerView = self.createOverlay(frame: CGRect(origin: data.point, size: data.size),
                //                                                            radius: data.radius,
                //                                                            animationStyle: .scale)
            case .move:
                self.currentMarkerView = self.createOverlay(frame: CGRect(origin: data.point, size: data.size),
                                                            radius: data.radius,
                                                            animationStyle: .move)
            }
            
            if let currentMarkerView = self.currentMarkerView {
                self.parentView.addSubview(currentMarkerView)
                self.currentIndex += 1
            }
        }
    }
    
    /// 圆型
    private func createOverlayCircle(offset: CGPoint, radius: CGFloat, animationStyle: JWGuideMarkerAnimationStyle = .none) -> UIView? {
        
        guard let ds = dataSource else { assert(false, "JWGuideMarkerManager.Error.请先配置数据源"); return nil }
        
        let overlayView = ds.guideMarker(self, viewForItemAtIndex: currentIndex)
        
        let firstPath = createCirclePath(size: overlayView.bounds.size, center: offset, radius: radius)
        let secondPath = createCirclePath(size: overlayView.bounds.size, center: offset, radius: radius + animationEffectOffsetValue)
        
        addAnimation(fromPath: firstPath, toPath: secondPath, overlayView: overlayView, animationStyle: animationStyle)
        
        return overlayView
    }
    
    /// 平移
    private func createOverlay(frame: CGRect, radius: CGFloat, animationStyle: JWGuideMarkerAnimationStyle = .none) -> UIView? {
        
        guard let ds = dataSource else { assert(false, "JWGuideMarkerManager.Error.请先配置数据源"); return nil }
        
        let overlayView = ds.guideMarker(self, viewForItemAtIndex: currentIndex)
        
        let firstPath = createSquarePath(frame: frame, radius: radius, size: overlayView.bounds.size, effectWidth: 0, effectHeight: 0)
        let secondPath = createSquarePath(frame: frame, radius: radius, size: overlayView.bounds.size, effectWidth: 0, effectHeight: animationEffectOffsetValue)
        
        addAnimation(fromPath: firstPath, toPath: secondPath, overlayView: overlayView, animationStyle: animationStyle)
        
        return overlayView
        
    }
    
    /// 添加动画
    private func addAnimation(fromPath: CGMutablePath,
                              toPath: CGMutablePath,
                              overlayView: UIView,
                              animationStyle: JWGuideMarkerAnimationStyle = .none) {
        
        /// 添加动画组
        func createAnimateGroup(animation: CAAnimation) -> CAAnimationGroup {
            let animates = CAAnimationGroup()
            animates.animations = [animation]
            animates.autoreverses = true
            animates.repeatCount = .infinity
            animates.duration = 0.4
            return animates
        }
        
        let shape = createShape(path: fromPath)
        if animationStyle != .none {
            let pathAnimation = CABasicAnimation(keyPath: "path")
            pathAnimation.fromValue = fromPath
            pathAnimation.toValue = toPath
            shape.add(createAnimateGroup(animation: pathAnimation), forKey: "ani")
        }
        overlayView.layer.mask = shape
        overlayView.clipsToBounds = true
    }
    
    /// 创建圆形蒙层
    private func createCirclePath(size: CGSize, center: CGPoint, radius: CGFloat) -> CGMutablePath {
        let path = CGMutablePath()
        path.addArc(center: center,
                    radius: radius,
                    startAngle: 0.0,
                    endAngle: 2.0 * .pi,
                    clockwise: false)
        path.addRect(CGRect(origin: .zero, size: size))
        return path
    }
    
    /// 创建方形蒙层
    private func createSquarePath(frame: CGRect, radius: CGFloat, size: CGSize, effectWidth: CGFloat, effectHeight: CGFloat) -> CGMutablePath {
        let path = CGMutablePath()
        let toSize = CGSize(width: frame.width, height: frame.height)
        path.addRoundedRect(in: CGRect(x: frame.origin.x - effectWidth,
                                       y: frame.origin.y - effectHeight,
                                       width: toSize.width,
                                       height: toSize.height),
                            cornerWidth: min(radius, toSize.width / 2.0),
                            cornerHeight: min(radius, toSize.height / 2.0))
        path.addRect(CGRect(origin: .zero, size: size))
        return path
    }
    
    /// 创建ShapeLayer蒙层
    private func createShape(path: CGPath) -> CAShapeLayer {
        let maskLayer = CAShapeLayer()
        maskLayer.backgroundColor = UIColor.black.cgColor
        maskLayer.path = path
        maskLayer.fillRule = CAShapeLayerFillRule.evenOdd
        return maskLayer
    }
    
}


/// 引导标识数据源
public protocol JWGuideMarkerManagerDataSource: NSObjectProtocol {
    
    /// 引导父层View
    /// func guideMarkerParentView(_ guideMarker: JWGuideMarkerManager) -> UIView
    
    /// 引导数
    func guideMarkerNumbers(_ guideMarker: JWGuideMarkerManager) -> Int
    
    /// 引导数据
    func guideMarker(_ guideMarker: JWGuideMarkerManager, markerForItemAtIndex index: Int) -> JWGuideMarkerData
    
    /// 引导View
    func guideMarker(_ guideMarker: JWGuideMarkerManager, viewForItemAtIndex index: Int) -> UIView
    
}
